package com.yindi.sftp.config;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.yindi.sftp.utils.Dom4jUtil;
import com.yindi.sftp.utils.JarToolUtil;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.Element;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author qing-feng.zhao
 */
@Slf4j
public class Parameters {

    public static final ExecutorService threadPool = Executors.newFixedThreadPool(10);

    private static final String COMMON = "Common";

    private static final String UPLOAD = "Upload";

    private static final String DOWNLOAD = "Download";

    private static final String DIRS = "Dirs";

    public static Common common;

    public static Upload upload;

    public static Download download;


    @Data
    @Builder
    public static class Common {

        private String serverIp;

        private String serverPort;

        private String userId;

        private String passwd;

        private String sleepTime;

        private String sockTimeout;
    }

    @Data
    @Builder
    public static class Upload {

        private String tmpDir;

        private List<Dir> dirs;

    }

    @Data
    @Builder
    public static class Download {

        private String tmpDir;

        private List<Dir> dirs;

    }

    @Data
    @Builder
    public static class Dir {

        private String id;

        private Common common;

        private String srcDir;

        private String dstDir;

        private List<String> bakDirs;

        private String active;

        private String deleteRemote;

        private String zip;
    }


    /**
     * 初始化配置
     */
    public static void init() {
        try {
            final InputStream resource;
            String file = JarToolUtil.getJarDir() + "/config.xml";
            if (FileUtil.exist(file)) {
                log.info("读取配置文件：{}", file);
                resource = Files.newInputStream(Paths.get(file));
            } else {
                resource = Parameters.class.getClassLoader().getResourceAsStream("config.xml");
            }
            //获取配置文件
            Document read = Dom4jUtil.read(resource);
            if (Objects.nonNull(read)) {
                //获取根节点
                Element rootElement = read.getRootElement();
                //获取所有的子节点
                List<Element> elements = rootElement.elements();
                for (Element e : elements) {
                    switch (e.getName()) {
                        case COMMON: {
                            List<Element> commonElements = e.elements();
                            Common.CommonBuilder builder = Common.builder();
                            for (Element commonElement : commonElements) {
                                if (Objects.equals(commonElement.getName(), "ServerIp")) {
                                    builder.serverIp(commonElement.getStringValue());
                                }
                                if (Objects.equals(commonElement.getName(), "ServerPort")) {
                                    builder.serverPort(commonElement.getStringValue());
                                }
                                if (Objects.equals(commonElement.getName(), "UserId")) {
                                    builder.userId(commonElement.getStringValue());
                                }
                                if (Objects.equals(commonElement.getName(), "Passwd")) {
                                    builder.passwd(commonElement.getStringValue());
                                }
                                if (Objects.equals(commonElement.getName(), "SockTimeout")) {
                                    builder.sockTimeout(commonElement.getStringValue());
                                }
                                if (Objects.equals(commonElement.getName(), "SleepTime")) {
                                    builder.sleepTime(commonElement.getStringValue());
                                }
                            }
                            common = builder.build();
                            break;
                        }
                        case UPLOAD: {
                            List<Element> uploadElements = e.elements();
                            Upload.UploadBuilder builder = Upload.builder();
                            for (Element uploadElement : uploadElements) {
                                if (Objects.equals(uploadElement.getName(), "TmpDir")) {
                                    builder.tmpDir(uploadElement.getStringValue());
                                }
                                if (Objects.equals(uploadElement.getName(), "Dirs")) {
                                    builder.dirs(getDirs(uploadElement));
                                }
                            }
                            upload = builder.build();
                            break;
                        }
                        case DOWNLOAD: {
                            List<Element> downloadElements = e.elements();
                            Download.DownloadBuilder builder = Download.builder();
                            for (Element uploadElement : downloadElements) {
                                if (Objects.equals(uploadElement.getName(), "TmpDir")) {
                                    builder.tmpDir(uploadElement.getStringValue());
                                }
                                if (Objects.equals(uploadElement.getName(), "Dirs")) {
                                    builder.dirs(getDirs(uploadElement));
                                }
                            }
                            download = builder.build();
                            break;
                        }
                    }
                }
            }

        } catch (Exception e) {
            //noinspection CallToPrintStackTrace
            e.printStackTrace();
            log.info("配置文件解析失败: {}", e.getMessage());
        }
    }

    public static List<Dir> getDirs(Element dirsElement) {
        List<Element> dirs = dirsElement.elements();
        List<Dir> dirList = new ArrayList<>();
        for (Element dir : dirs) {
            Dir.DirBuilder dirBuilder = Dir.builder()
                    .id(dir.attributeValue("id"))
                    .common(Common.builder()
                            .serverIp(Objects.isNull(dir.attributeValue("ip"))? common.serverIp : dir.attributeValue("ip"))
                            .serverPort(Objects.isNull(dir.attributeValue("port"))? common.serverPort : dir.attributeValue("port"))
                            .userId(Objects.isNull(dir.attributeValue("userId"))? common.userId : dir.attributeValue("userId"))
                            .passwd(Objects.isNull(dir.attributeValue("passwd"))? common.passwd : dir.attributeValue("passwd"))
                            .build())
                    .srcDir(dir.attributeValue("srcDir"))
                    .dstDir(dir.attributeValue("dstDir"))
                    .active(dir.attributeValue("active"))
                    .deleteRemote(dir.attributeValue("deleteRemote"))
                    .zip(dir.attributeValue("zip"));
            //单独处理 bakDirs
            String s = dir.attributeValue("bakDirs");
            if (StrUtil.isNotBlank(s)) {
                List<String> bakDirs = new ArrayList<>();
                if (s.indexOf(',') > 0) {
                    String[] split = s.split(",");
                    for (String bakDir : split) {
                        if (StrUtil.isNotBlank(bakDir)) {
                            bakDirs.add(bakDir);
                        }
                    }
                } else {
                    bakDirs.add(s);
                }
                dirBuilder.bakDirs(bakDirs);
            }
            dirList.add(dirBuilder.build());
        }
        return dirList;
    }
}